﻿using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using PMS.Domain.Seedwork;
using PMS.Infrastructure;
using System;
using System.Threading;
using System.Threading.Tasks;
using PMS.Domain.AggregatesModel.ProjectAggregate;
using PMS.Infrastructure.EntityConfigurations;
using PMS.Domain.AggregatesModel.MessaeAggregate;

namespace PMS.Infrastructure
{
    public class PMSContext :DbContext , IUnitOfWork
    {
      
        private readonly IMediator _mediator;

        private PMSContext(DbContextOptions<PMSContext> options) : base (options) { }

        public PMSContext(DbContextOptions<PMSContext> options, IMediator mediator) : base(options)
        {
            _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));         
        }
        #region 项目相关
        /// <summary>
        /// 项目仓储
        /// </summary>
        public DbSet<Project> Projects { get; set; }

        /// <summary>
        /// 项目状态
        /// </summary>
        public DbSet<ProjectStatus> ProjectStatus { get; set; }

        /// <summary>
        /// 项目审核状态
        /// </summary>
        public DbSet<ProjectAuditStatus> ProjectAuditStatus { get; set; }
        #endregion

        #region 消息中心
        public DbSet<MessageCenter> MessageCenters { get; set; }
        #endregion


        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.ApplyConfiguration(new ProjectAuditAdviceEntityConfiguration());
            modelBuilder.ApplyConfiguration(new ProjectAuditStatusEntityConfiguration());
            modelBuilder.ApplyConfiguration(new ProjectContributorEntityConfiguration());
            modelBuilder.ApplyConfiguration(new ProjectConsumableEntityConfiguration());
            modelBuilder.ApplyConfiguration(new ProjectStatusEntityConfiguration());
            modelBuilder.ApplyConfiguration(new ProjectEntityConfiguration());

            modelBuilder.ApplyConfiguration(new MessageCenterEntityConfiguration());


        }

        public async Task<bool> SaveEntitiesAsync(CancellationToken cancellationToken = default(CancellationToken))
        {
            // Dispatch Domain Events collection. 
            // Choices:
            // A) Right BEFORE committing data (EF SaveChanges) into the DB will make a single transaction including  
            // side effects from the domain event handlers which are using the same DbContext with "InstancePerLifetimeScope" or "scoped" lifetime
            // B) Right AFTER committing data (EF SaveChanges) into the DB will make multiple transactions. 
            // You will need to handle eventual consistency and compensatory actions in case of failures in any of the Handlers. 
            await _mediator.DispatchDomainEventsAsync(this);

            // After executing this line all the changes (from the Command Handler and Domain Event Handlers) 
            // performed throught the DbContext will be commited
            var result = await base.SaveChangesAsync();

            return true;
        }        
    }   
}
